using System.Linq;
using RockHopper.TrainingCalculator.WinRT.Utils;
using Windows.Graphics.Display;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

namespace RockHopper.TrainingCalculator.WinRT.Controls
{
    public class TileLayoutControl : ItemsControl
    {
        private Grid grid;

        public TileLayoutControl()
        {
            DefaultStyleKey = typeof(TileLayoutControl);
        }

        public static readonly DependencyProperty LandscapeRowProperty =
            DependencyPropertyDescriptor.CreateAttached<TileLayoutControl, int>("LandscapeRow");

        public static void SetLandscapeRow(UIElement element, int value)
        {
            element.SetValue(LandscapeRowProperty, value);
        }

        public static int GetLandscapeRow(UIElement element)
        {
            return (int)element.GetValue(LandscapeRowProperty);
        }

        public static readonly DependencyProperty LandscapeColumnProperty =
            DependencyPropertyDescriptor.CreateAttached<TileLayoutControl, int>("LandscapeColumn");

        public static void SetLandscapeColumn(UIElement element, int value)
        {
            element.SetValue(LandscapeColumnProperty, value);
        }

        public static int GetLandscapeColumn(UIElement element)
        {
            return (int)element.GetValue(LandscapeColumnProperty);
        }

        public static readonly DependencyProperty PortraitRowProperty =
            DependencyPropertyDescriptor.CreateAttached<TileLayoutControl, int>("PortraitRow");

        public static void SetPortraitRow(UIElement element, int value)
        {
            element.SetValue(PortraitRowProperty, value);
        }

        public static int GetPortraitRow(UIElement element)
        {
            return (int)element.GetValue(PortraitRowProperty);
        }

        public static readonly DependencyProperty PortraitColumnProperty =
            DependencyPropertyDescriptor.CreateAttached<TileLayoutControl, int>("PortraitColumn");

        public static void SetPortraitColumn(UIElement element, int value)
        {
            element.SetValue(PortraitColumnProperty, value);
        }

        public static int GetPortraitColumn(UIElement element)
        {
            return (int)element.GetValue(PortraitColumnProperty);
        }

        public static readonly DependencyProperty RowSpanProperty =
            DependencyPropertyDescriptor.CreateAttached<TileLayoutControl, int>("RowSpan");

        public static void SetRowSpan(UIElement element, int value)
        {
            element.SetValue(RowSpanProperty, value);
        }

        public static int GetRowSpan(UIElement element)
        {
            return (int)element.GetValue(RowSpanProperty);
        }

        public static readonly DependencyProperty ColumnSpanProperty =
            DependencyPropertyDescriptor.CreateAttached<TileLayoutControl, int>("ColumnSpan");

        public static void SetColumnSpan(UIElement element, int value)
        {
            element.SetValue(ColumnSpanProperty, value);
        }

        public static int GetColumnSpan(UIElement element)
        {
            return (int)element.GetValue(ColumnSpanProperty);
        }

        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            grid = (Grid) GetTemplateChild("GridPart");

            foreach (FrameworkElement item in Items)
            {
                grid.Children.Add(item);
            }

            UpdateGridLayout();

            DisplayProperties.OrientationChanged += s => UpdateGridLayout();
        }

        private void UpdateGridLayout()
        {
            grid.RowDefinitions.Clear();
            grid.ColumnDefinitions.Clear();

            if (DisplayPropertiesHelper.IsPortrait)
            {
                LayoutPortrait();
            }
            else
            {
                LayoutLandscape();
            }
        }

        private void LayoutLandscape()
        {
            AddRowDefinitions(6);
            AddColumnDefinitions(12);
            AssignItemLandscapePositions();
        }

        private void LayoutPortrait()
        {
            AddRowDefinitions(12);
            AddColumnDefinitions(6);
            AssignItemPortraitPositions();
        }

        private void AddRowDefinitions(int count)
        {
            for (var i = 0; i < count; i++)
            {
                grid.RowDefinitions.Add(new RowDefinition());

                if (i > 0 && i < count - 1)
                    grid.RowDefinitions.Last().Height = new GridLength(100);
            }
        }

        private void AddColumnDefinitions(int count)
        {
            for (var i = 0; i < count; i++)
            {
                grid.ColumnDefinitions.Add(new ColumnDefinition());

                if (i > 0 && i < count - 1)
                    grid.ColumnDefinitions.Last().Width = new GridLength(100);
            }
        }

        private void AssignItemLandscapePositions()
        {
            foreach (FrameworkElement item in Items)
            {
                var row = GetLandscapeRow(item);
                var col = GetLandscapeColumn(item);
                Grid.SetRow(item, row);
                Grid.SetColumn(item, col);
                AssignItemGridSpan(item);
            }
        }

        private void AssignItemPortraitPositions()
        {
            foreach (FrameworkElement item in Items)
            {
                var row = GetPortraitRow(item);
                var col = GetPortraitColumn(item);
                Grid.SetRow(item, row);
                Grid.SetColumn(item, col);
                AssignItemGridSpan(item);
            }
        }
        private void AssignItemGridSpan(FrameworkElement item)
        {
            var rowSpan = GetRowSpan(item);
            var colSpan = GetRowSpan(item);

            if (rowSpan > 1) Grid.SetRowSpan(item, rowSpan);
            if (colSpan > 1) Grid.SetColumnSpan(item, colSpan);
        }
    }
}